package view;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import worldModel.*;
import battleFieldModel.*;

/**
 * JavaBoy 9
 * 
 * @author Gopal Adhikari, Alex James Topping
 * @version 9
 * 
 */

/**
 * WorldView GUI provider for JavaBoy. This class encapsulates MasterView,
 * Navigator and World classes in to it and provides a graphical view for each.
 * 
 */
public class WorldView extends MasterViewPanel implements Observer {

    private static final long serialVersionUID = -629796683513197443L;

    private Navigator nav;
    private Image floorTile;
    private MasterView m;
    private World world;
    private BufferedImage navigatorSpriteSheet;

    static int offSetX = 0;
    static int offSetY = 0;

    public WorldView(MasterView m, Navigator n) {

	super(m);
	this.m = m;
	this.nav = n;
	this.world = new World(this.nav);

	try {
	    floorTile = new ImageIcon("images/floorPanel.png").getImage();
	    navigatorSpriteSheet = ImageIO
		    .read(new File("images/navigator.png"));
	} catch (Exception ex) {
	    System.out.println("floorPanel.png or navigator.png not found!");
	}

	KeyListener key = new KeyListener() {

	    @Override
	    public void keyTyped(KeyEvent e) {
	    }

	    @Override
	    public void keyReleased(KeyEvent e) {
	    }

	    @Override
	    public void keyPressed(KeyEvent e) {
		try {
		    int keyCode = e.getKeyCode();
		    if (keyCode == KeyEvent.VK_DOWN) {
			offSetY = 0;
			offSetX += 32;
			offSetX = (offSetX == 96) ? 0 : offSetX;
			world.move(Direction.SOUTH_EAST);
			repaint();
		    }

		    else if (keyCode == KeyEvent.VK_UP) {
			offSetX += 32;
			offSetX = (offSetX == 96) ? 0 : offSetX;
			offSetY = 96;
			world.move(Direction.NORTH_WEST);
			repaint();
		    }

		    else if (keyCode == KeyEvent.VK_LEFT) {
			offSetX += 32;
			offSetX = (offSetX == 96) ? 0 : offSetX;
			offSetY = 32;
			world.move(Direction.SOUTH_WEST);
			repaint();
		    }

		    else if (keyCode == KeyEvent.VK_RIGHT) {
			offSetX += 32;
			offSetX = (offSetX == 96) ? 0 : offSetX;
			offSetY = 64;
			world.move(Direction.NORTH_EAST);
			repaint();

		    } else if (keyCode == KeyEvent.VK_X) {

			List<Item> smallHealItems = new ArrayList<Item>();
			List<Item> mediumHealItems = new ArrayList<Item>();
			List<Item> largeHealItems = new ArrayList<Item>();
			//
			// smallHealItems.add(new SmallHeal());
			// smallHealItems.add(new SmallHeal());
			// smallHealItems.add(new SmallHeal());

			for (Item item : nav.getInventory()) {
			    if (item.toString().equals("SmallHeal")) {
				smallHealItems.add(item);
			    } else if (item.toString().equals("MediumHeal")) {
				mediumHealItems.add(item);
			    } else if (item.toString().equals("LargeHeal")) {
				largeHealItems.add(item);
			    }
			}

			int smallCount = (smallHealItems.size() != 0 || smallHealItems != null) ? smallHealItems
				.size() : 0;
			int mediumCount = (mediumHealItems.size() != 0 || mediumHealItems != null) ? mediumHealItems
				.size() : 0;
			int largeCount = (largeHealItems.size() != 0 || largeHealItems != null) ? largeHealItems
				.size() : 0;

			String dialogTitle = "Player Health: "
				+ nav.getPlayer().getHealth();

			List<String> optionsList = new ArrayList<String>();

			optionsList.add("Small Heal (" + smallCount + ")");

			optionsList.add("Medium Heal (" + mediumCount + ")");

			optionsList.add("Large Heal (" + largeCount + ")");

			Object[] options = { optionsList.get(0),
				optionsList.get(1), optionsList.get(2),
				"Quit Game", "Back to Game" };

			int response = JOptionPane.showOptionDialog(null,
				"What would you like to do?", dialogTitle,
				JOptionPane.DEFAULT_OPTION,
				JOptionPane.QUESTION_MESSAGE, null, options,
				options[0]);

			/*
			 * The response keeps tracks of the user's choice from
			 * the option dialog box. If response = 0: Small Heal If
			 * response=4 :Back to game
			 */

			switch (response) {
			case 0:
			    if (smallCount != 0) {
				if (nav.getPlayer().getHealth() < 100) {
				    smallHealItems.get(0).activateEffect(nav);
				    smallHealItems.remove(0);
				    smallCount = smallHealItems.size();
				} else {
				    JOptionPane
					    .showMessageDialog(null,
						    "Your health is already maxed out, N00B!");
				}
			    }
			    break;
			case 1:
			    if (mediumCount != 0) {
				if (nav.getPlayer().getHealth() < 100) {
				    mediumHealItems.get(0).activateEffect(nav);
				    mediumHealItems.remove(0);
				    mediumCount = mediumHealItems.size();
				} else {
				    JOptionPane
					    .showMessageDialog(null,
						    "Your health is already maxed out, N00B!");
				}
			    }
			    break;
			case 2:
			    if (largeCount != 0) {
				if (nav.getPlayer().getHealth() < 100) {
				    largeHealItems.get(0).activateEffect(nav);
				    largeHealItems.remove(0);
				    largeCount = largeHealItems.size();
				} else {
				    JOptionPane
					    .showMessageDialog(null,
						    "Your health is already maxed out, N00B!");
				}
			    }
			    break;

			case 3:
			    saveGame();
			    System.exit(0);
			    break;
			case 4:
			    break;
			}

			nav.getInventory().clear();

			nav.getInventory().addAll(smallHealItems);
			nav.getInventory().addAll(mediumHealItems);
			nav.getInventory().addAll(largeHealItems);

			for (Item i : nav.getInventory()) {
			    nav.addItem(i);
			}

			SaveGameHelper.saveGame(nav);
		    }

		} catch (Exception ex) {
		    ex.printStackTrace();
		}

	    }

	    private void saveGame() {
		SaveGameHelper.saveGame(nav);
	    }
	};

	this.addKeyListener(key);
	world.addObserver(this);
	this.setFocusable(true);
    }

    @Override
    protected void paintComponent(Graphics g) {

	super.paintComponent(g);
	Graphics2D g2d = (Graphics2D) g;
	Iterator<WorldTile> worldTileItr = world.tiles(nav.getLocation());

	while (worldTileItr.hasNext()) {

	    WorldTile tile = worldTileItr.next();

	    int r = nav.getLocation().row - tile.getLocation().row;
	    int c = nav.getLocation().col - tile.getLocation().col;

	    int x = 280 + (32 * r) - (32 * c) + nav.getLeeway().row
		    - nav.getLeeway().col;
	    int y = 170 - (32 * c) - (32 * r) - nav.getLeeway().row
		    - nav.getLeeway().col;

	    g.drawImage(floorTile, x, y, null);

	}

	g2d.drawImage(
		navigatorSpriteSheet.getSubimage(offSetX, offSetY, 32, 32),
		306, 151, 32, 32, null);
    }

    @Override
    public void update(Observable o, Object arg) {
	if (arg == null) {
	    this.repaint();
	} else if (arg instanceof BattleField) {
	    m.changeView(Views.BATTLE, arg);
	} else if (arg == Views.PREVIOUS) {
	    m.changeView(Views.PREVIOUS, null);
	}
    }

}